package com.black.platform.dictionary.service.handler.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.black.common.vo.DictionaryTreeVo;
import com.black.common.web.PageQuery;
import com.black.platform.dictionary.po.Dictionary;
import com.black.platform.dictionary.service.bz.DictionaryService;
import com.black.platform.dictionary.service.handler.DictionaryHandlerService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class DictionaryHandlerServiceImpl implements DictionaryHandlerService {

    private final DictionaryService dictionaryService;

    @Override
    public IPage<DictionaryTreeVo> search(PageQuery<Dictionary> searchVo) {
        IPage<Dictionary> searchResult = dictionaryService.search(searchVo);
        List<DictionaryTreeVo> dictionaryTreeVos = buildCodeTypeSelectTree(searchResult.getRecords());
        IPage<DictionaryTreeVo> pageData = new Page<>();
        pageData.setRecords(dictionaryTreeVos);
        pageData.setCurrent(searchResult.getCurrent());
        pageData.setTotal(searchResult.getTotal());
        pageData.setSize(searchResult.getSize());
        return pageData;

    }

    @Override
    public Dictionary getById(Long id) {
        return dictionaryService.getById(id);
    }

    @Override
    public List<Dictionary> getByCodeType(String codeType, boolean isIncludeInvalid) {
        return dictionaryService.getByCodeType(codeType, isIncludeInvalid);
    }

    @Override
    public boolean deleteByIds(List<Long> ids) {
        return dictionaryService.removeByIds(ids);
    }

    @Override
    public List<DictionaryTreeVo> getDictionaryTreeVo() {
        List<Dictionary> allValidDictionaryList = dictionaryService.getAllValidDictionaryList();
        return this.buildCodeTypeSelectTree(allValidDictionaryList);
    }

    @Override
    public boolean save(Dictionary dictionary) {
        return dictionaryService.save(dictionary);
    }

    @Override
    public boolean update(Dictionary dictionary) {
        return dictionaryService.saveOrUpdate(dictionary);
    }

    @Override
    public List<DictionaryTreeVo> getAllCodeTypeTreeVo() {
        return buildCodeTypeSelectTree(dictionaryService.getAllCodeType());
    }

    /***
     * 构建数据字典树
     * @param dictionaryList 数据字典集合
     * @return 数据字典树集
     */
    private List<DictionaryTreeVo> buildCodeTypeSelectTree(List<Dictionary> dictionaryList) {
        List<DictionaryTreeVo> voList = new ArrayList<>();
        Map<String, DictionaryTreeVo> voMap = dictionaryList.stream().collect(Collectors.toMap(Dictionary::getCode, codeType -> {
            DictionaryTreeVo dictionaryTreeVo = new DictionaryTreeVo();
            BeanUtils.copyProperties(codeType, dictionaryTreeVo);
            return dictionaryTreeVo;
        }));
        dictionaryList.sort(Comparator.comparingInt(Dictionary::getOrders));
        for (Dictionary dictionary : dictionaryList) {
            if (StringUtils.isEmpty(dictionary.getParentCode())) {
                voList.add(voMap.get(dictionary.getCode()));
            } else {
                DictionaryTreeVo dictionaryTreeVo = voMap.get(dictionary.getParentCode());
                if (dictionaryTreeVo != null) {
                    if (dictionaryTreeVo.getChildren() == null) {
                        dictionaryTreeVo.setChildren(new ArrayList<>());
                        dictionaryTreeVo.set_showChildren(true);
                    }
                    dictionaryTreeVo.getChildren().add(voMap.get(dictionary.getCode()));
                } else {
                    voList.add(voMap.get(dictionary.getCode()));
                }
            }
        }
        return voList;
    }
}
